{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {
    "lang": "hi"
   },
   "source": [
    "# भाग 4: मॉडेल एव्हरेजिंगसह फेडरटेड लर्निंग(Federated Learning)\n",
    "\n",
    "**पूर्वी:** या ट्यूटोरियलच्या भाग 2 मध्ये, आपण फेडरेट लर्निंगची (Federated Learning) अगदी सोपी आवृत्ती वापरुन एक मॉडेल प्रशिक्षित (Train) केले. मॉडेलच्या मालकाचे ग्रेडियंट्स (Gradients) पाहण्यात सक्षम होण्यासाठी यावर विश्वास ठेवणे आवश्यक आहे.\n",
    "\n",
    "**वर्णनः** अंतिम परिणामी मॉडेल, मॉडेलच्या मालकाला (आपल्याला) परत पाठविण्यापूर्वी विश्वासू \"सुरक्षित कामगार\"(secure worker) द्वारे वजन एकत्रित करण्यास भाग 3 मधील प्रगत एकत्रीकरण साधने कशी वापरायची हे या ट्यूटोरियलमध्ये आपण दर्शवू.\n",
    "\n",
    "अशाप्रकारे, केवळ सुरक्षित कामगार कोणाचे वजन (weights) कोणाकडून आले हे पाहू शकते. आपण मॉडेलचे कोणते भाग बदलले हे सांगण्यास सक्षम असू, परंतु कोणत्या कामगार (Bob किंवा Alice) ने कोणता बदल केला हे आपल्याला माहित नाही, ज्यामुळे गोपनीयतेचा स्तर तयार होतो.\n",
    "\n",
    "लेखक:\n",
    "\n",
    " - Andrew Trask - Twitter: [@iamtrask](https://twitter.com/iamtrask)\n",
    " - Jason Mancuso - Twitter: [@jvmancuso](https://twitter.com/jvmancuso)\n",
    " \n",
    "\n",
    "अनुवादक/संपादक:\n",
    "\n",
    " - Krunal Kshirsagar - Twitter: [@krunal_wrote](https://twitter.com/krunal_wrote)· Github: [@Noob-can-Compile](https://github.com/Noob-can-Compile)\n",
    " \n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import torch\n",
    "import syft as sy\n",
    "import copy\n",
    "hook = sy.TorchHook(torch)\n",
    "from torch import nn, optim"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "lang": "hi"
   },
   "source": [
    "# चरण 1: डेटाचे मालक तयार करा\n",
    "\n",
    "प्रथम, आपण कमी डेटासह प्रत्येकी दोन डेटा मालक (Bob आणि Alice) तयार करणार आहोत. आपण \"secure_worker\" नावाच्या एक सुरक्षित मशीनला प्रारंभ देखील करणार आहोत. सराव मध्ये हे सुरक्षित हार्डवेअर (जसे की इंटेलचे SGX) किंवा फक्त विश्वासू मध्यस्थ असू शकते."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# create a couple workers\n",
    "\n",
    "bob = sy.VirtualWorker(hook, id=\"bob\")\n",
    "alice = sy.VirtualWorker(hook, id=\"alice\")\n",
    "secure_worker = sy.VirtualWorker(hook, id=\"secure_worker\")\n",
    "\n",
    "\n",
    "# A Toy Dataset\n",
    "data = torch.tensor([[0,0],[0,1],[1,0],[1,1.]], requires_grad=True)\n",
    "target = torch.tensor([[0],[0],[1],[1.]], requires_grad=True)\n",
    "\n",
    "# get pointers to training data on each worker by\n",
    "# sending some training data to bob and alice\n",
    "bobs_data = data[0:2].send(bob)\n",
    "bobs_target = target[0:2].send(bob)\n",
    "\n",
    "alices_data = data[2:].send(alice)\n",
    "alices_target = target[2:].send(alice)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "lang": "hi"
   },
   "source": [
    "# चरण 2: आमचे मॉडेल तयार करा\n",
    "\n",
    "या उदाहरणार्थ, आम्ही एक सोपी रेखीय (Linear) मॉडेल प्रशिक्षित(Training) करणार आहोत. Pytorch चे nn.Linear कन्स्ट्रक्टर वापरुन आपण सामान्यपणे हे आरंभ करू शकतो."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Iniitalize A Toy Model\n",
    "model = nn.Linear(2,1)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "lang": "hi"
   },
   "source": [
    "# चरण 3: Alice आणि Bob ला  मॉडेलची एक प्रत पाठवा\n",
    "\n",
    "पुढे, आपल्याला सध्याच्या मॉडेलची एक प्रत Alice आणि Bob कडे पाठविणे आवश्यक आहे जेणेकरून ते त्यांच्या स्वत: च्या डेटासेटवर शिकण्याच्या चरणांचे(स्टेप्स ऑफ learning) प्रदर्शन करू शकतील."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "bobs_model = model.copy().send(bob)\n",
    "alices_model = model.copy().send(alice)\n",
    "\n",
    "bobs_opt = optim.SGD(params=bobs_model.parameters(),lr=0.1)\n",
    "alices_opt = optim.SGD(params=alices_model.parameters(),lr=0.1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "lang": "hi"
   },
   "source": [
    "# चरण 4: Bob आणि Alice चे मॉडेल प्रशिक्षित करा (समांतर मध्ये).\n",
    "\n",
    "जसे सिक्युअर एव्हरेजिंगद्वारे फेडरेटेड लर्निंग(Federated Learning) पारंपारिक आहे, प्रत्येक डेटा मालक मॉडेल एकत्रितपणे सरासरी काढण्यापूर्वी प्रथम त्यांचे मॉडेल स्थानिक पातळीवर अनेक पुनरावृत्तीसाठी प्रशिक्षित करतात."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "for i in range(10):\n",
    "\n",
    "    # Train Bob's Model\n",
    "    bobs_opt.zero_grad()\n",
    "    bobs_pred = bobs_model(bobs_data)\n",
    "    bobs_loss = ((bobs_pred - bobs_target)**2).sum()\n",
    "    bobs_loss.backward()\n",
    "\n",
    "    bobs_opt.step()\n",
    "    bobs_loss = bobs_loss.get().data\n",
    "\n",
    "    # Train Alice's Model\n",
    "    alices_opt.zero_grad()\n",
    "    alices_pred = alices_model(alices_data)\n",
    "    alices_loss = ((alices_pred - alices_target)**2).sum()\n",
    "    alices_loss.backward()\n",
    "\n",
    "    alices_opt.step()\n",
    "    alices_loss = alices_loss.get().data\n",
    "    \n",
    "    print(\"Bob:\" + str(bobs_loss) + \" Alice:\" + str(alices_loss))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "lang": "hi"
   },
   "source": [
    "# चरण 5: एका सुरक्षित कामगारा कडे अद्ययावत केलेली दोन्ही मॉडेल्स पाठवा\n",
    "\n",
    "आता प्रत्येक डेटा मालकाचे अर्धवट प्रशिक्षित मॉडेल आहे, त्यांना सुरक्षित मार्गाने एकत्र आणण्याची वेळ आली आहे. Alice आणि Bob चे मॉडेल सुरक्षित (विश्वसनीय) सर्व्हरवर पाठविण्याची सूचना देऊन आम्ही हे साध्य केले.\n",
    "\n",
    "लक्षात ठेवा की आमच्या एपीआयच्या (API) वापराचा अर्थ असा आहे की प्रत्येक मॉडेल सुरक्षित कर्त्याकडे (secure_worker) थेट पाठविले जाते. आपण ते कधीच पाहत नाही."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "alices_model.move(secure_worker)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "bobs_model.move(secure_worker)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "lang": "hi"
   },
   "source": [
    "# चरण 6: मॉडेल्सची सरासरी "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "lang": "hi"
   },
   "source": [
    "अखेरीस, या प्रशिक्षण युगाची शेवटची पायरी म्हणजे Bob आणि Alice च्या प्रशिक्षित मॉडेल्सची सरासरी एकत्र करणे आणि नंतर आपल्या जागतिक \"मॉडेल\" साठी मूल्ये सेट करण्यासाठी याचा वापर करा."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "with torch.no_grad():\n",
    "    model.weight.set_(((alices_model.weight.data + bobs_model.weight.data) / 2).get())\n",
    "    model.bias.set_(((alices_model.bias.data + bobs_model.bias.data) / 2).get())\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "lang": "hi"
   },
   "source": [
    "# पुन्हा करा\n",
    "\n",
    "आणि आता आपल्याला बर्‍याच वेळा पुनरावृत्ती करण्याची आवश्यकता आहे!"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "iterations = 10\n",
    "worker_iters = 5\n",
    "\n",
    "for a_iter in range(iterations):\n",
    "    \n",
    "    bobs_model = model.copy().send(bob)\n",
    "    alices_model = model.copy().send(alice)\n",
    "\n",
    "    bobs_opt = optim.SGD(params=bobs_model.parameters(),lr=0.1)\n",
    "    alices_opt = optim.SGD(params=alices_model.parameters(),lr=0.1)\n",
    "\n",
    "    for wi in range(worker_iters):\n",
    "\n",
    "        # Train Bob's Model\n",
    "        bobs_opt.zero_grad()\n",
    "        bobs_pred = bobs_model(bobs_data)\n",
    "        bobs_loss = ((bobs_pred - bobs_target)**2).sum()\n",
    "        bobs_loss.backward()\n",
    "\n",
    "        bobs_opt.step()\n",
    "        bobs_loss = bobs_loss.get().data\n",
    "\n",
    "        # Train Alice's Model\n",
    "        alices_opt.zero_grad()\n",
    "        alices_pred = alices_model(alices_data)\n",
    "        alices_loss = ((alices_pred - alices_target)**2).sum()\n",
    "        alices_loss.backward()\n",
    "\n",
    "        alices_opt.step()\n",
    "        alices_loss = alices_loss.get().data\n",
    "    \n",
    "    alices_model.move(secure_worker)\n",
    "    bobs_model.move(secure_worker)\n",
    "    with torch.no_grad():\n",
    "        model.weight.set_(((alices_model.weight.data + bobs_model.weight.data) / 2).get())\n",
    "        model.bias.set_(((alices_model.bias.data + bobs_model.bias.data) / 2).get())\n",
    "    \n",
    "    print(\"Bob:\" + str(bobs_loss) + \" Alice:\" + str(alices_loss))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "lang": "hi"
   },
   "source": [
    "शेवटी, आपण हे सुनिश्चित करू इच्छित आहोत की आपले परिणामी मॉडेल योग्य प्रकारे शिकले आहे, म्हणून आपण त्याचे परीक्षण एका डेटासेटवर करू. या खेळण्यातील समस्येमध्ये आपण मूळ डेटा वापरू, परंतु प्रत्यक्षात न पाहिले गेलेल्या उदाहरणांना मॉडेल नेमक्या कोणत्या प्रकारे सामान्यीकृत केले हे समजून घेण्यासाठी आपल्याला नवीन डेटा वापरायचा आहे."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "preds = model(data)\n",
    "loss = ((preds - target) ** 2).sum()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "print(preds)\n",
    "print(target)\n",
    "print(loss.data)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "lang": "hi"
   },
   "source": [
    "या बनावट उदाहरणात, सरासरी मॉडेल स्थानिक पातळीवर प्रशिक्षित प्लेन टेक्स्ट मॉडेलच्या तुलनेत (underfitting) आहे, परंतु प्रत्येक कामगारांचा प्रशिक्षण डेटा उघड न करता आपण ते प्रशिक्षित करू शकलो. आपण मॉडेलच्या मालकाकडे डेटा गळती रोखण्यासाठी विश्वासू अ‍ॅग्रीगेटरवर प्रत्येक कामगारांकडील अद्ययावत मॉडेल्स एकत्रित करण्यास सक्षम होतो.\n",
    "\n",
    "भविष्यातील ट्यूटोरियल मध्ये, आमचे विश्वासार्ह एकत्रीकरण थेट ग्रेडीयंट्ससह (Gradient) करणे हे आमचे लक्ष्य आहे जेणेकरुन आपण मॉडेलला अधिक चांगल्या ग्रेडियंट (Gradient) अंदाजासह (estimates) अद्यतनित करू आणि अधिक मजबूत मॉडेलवर येऊ."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "lang": "hi"
   },
   "source": [
    "# अभिनंदन !!! - समुदायात सामील होण्याची वेळ आली!\n",
    "\n",
    "\n",
    "हे नोटबुक ट्यूटोरियल पूर्ण केल्याबद्दल अभिनंदन! आपण याचा आनंद घेत असल्यास आणि एआय(AI) आणि एआय सप्लाय चेन  (डेटा) च्या विकेंद्रित(Decentralized) मालकीच्या गोपनीयतेच्या संरक्षणाच्या दिशेने चळवळीत सामील होऊ इच्छित असाल तर आपण हे खालील प्रकारे करू शकता!\n",
    "\n",
    "### Pysyft ला Github वर Star करा!\n",
    "\n",
    "आमच्या समुदायाला मदत करण्याचा सर्वात सोपा मार्ग म्हणजे फक्त गिटहब(GitHub) रेपो(Repo) तारांकित(Star) करणे! हे आम्ही तयार करीत असलेल्या छान साधनांविषयी जागरूकता वाढविण्यास मदत करते.\n",
    "\n",
    "- [Star PySyft](https://github.com/OpenMined/PySyft)\n",
    "\n",
    "### आमच्या Slack मध्ये सामील व्हा!\n",
    "\n",
    "\n",
    "नवीनतम प्रगतीवर अद्ययावत राहण्याचा उत्तम मार्ग म्हणजे आमच्या समुदायामध्ये सामील होणे! आपण [http://slack.openmined.org](http://slack.openmined.org) येथे फॉर्म भरुन तसे करू शकता.\n",
    "\n",
    "### एका कोड प्रोजेक्टमध्ये सामील व्हा!\n",
    "\n",
    "आमच्या समुदायामध्ये योगदानाचा उत्तम मार्ग म्हणजे कोड योगदानकर्ता बनणे! कोणत्याही वेळी आपण (PySyft GitHub Issues Page) वर  जाऊ शकता आणि \"Project\" साठी फिल्टर करू शकता. हे आपण कोणत्या प्रकल्पांमध्ये सामील होऊ शकता याबद्दल विहंगावलोकन देणारी सर्व उच्च स्तरीय तिकिटे दर्शवेल! आपण एखाद्या प्रकल्पात सामील होऊ इच्छित नसल्यास, परंतु आपण थोडं कोडिंग करू इच्छित असाल तर आपण \"good first issues\" म्हणून चिन्हांकित गिटहब(GitHub) अंक शोधून आणखी \"one off\" मिनी-प्रकल्प(mini project) शोधू शकता.\n",
    "\n",
    "- [PySyft Projects](https://github.com/OpenMined/PySyft/issues?q=is%3Aopen+is%3Aissue+label%3AProject)\n",
    "- [Good First Issue Tickets](https://github.com/OpenMined/PySyft/issues?q=is%3Aopen+is%3Aissue+label%3A%22good+first+issue%22)\n",
    "\n",
    "### दान करा\n",
    "\n",
    "आपल्याकडे आमच्या कोडेबेसमध्ये योगदान देण्यास वेळ नसल्यास, परंतु तरीही आपल्याला समर्थन द्यावयाचे असल्यास आपण आमच्या मुक्त संग्रहात बॅकर देखील होऊ शकता. सर्व देणगी आमच्या वेब होस्टिंग आणि हॅकॅथॉन आणि मेटअप्स सारख्या इतर सामुदायिक खर्चाकडे जातात!\n",
    "\n",
    "[OpenMined's Open Collective Page](https://opencollective.com/openmined)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.3"
  },
  "nbTranslate": {
   "displayLangs": [
    "hi"
   ],
   "hotkey": "alt-t",
   "langInMainMenu": true,
   "sourceLang": "en",
   "targetLang": "hi",
   "useGoogleTranslate": true
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}